http://....¶numpy con respecto a trabajar en Python 'puro'.for puede afectar en la eficiencia en al procesar datos masivos.El laboratorio deberá ser desarrollado sin el uso indiscriminado de iteradores nativos de python (aka "for", "while"). La idea es que aprendan a exprimir al máximo las funciones optimizadas que nos entrega numpy, las cuales vale mencionar, son bastante más eficientes que los iteradores nativos sobre arreglos (o tensores).
# Libreria Core del lab.
import numpy as np
!pip install --upgrade pandas
!pip install xlrd
!pip install openpyxl
import pandas as pd
import datetime
from scipy import stats
from IPython.display import display, Markdown, Latex
#Libreria para plotear
!pip install --upgrade plotly
!pip install missingno
import matplotlib.pyplot as plt
import missingno as msno
import plotly.express as px
Requirement already satisfied: pandas in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (2.0.1) Requirement already satisfied: pytz>=2020.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from pandas) (2022.7) Requirement already satisfied: numpy>=1.20.3 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from pandas) (1.22.4) Requirement already satisfied: python-dateutil>=2.8.2 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from pandas) (2.8.2) Requirement already satisfied: tzdata>=2022.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from pandas) (2023.3) Requirement already satisfied: six>=1.5 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0) Requirement already satisfied: xlrd in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (2.0.1) Requirement already satisfied: openpyxl in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (3.0.10) Requirement already satisfied: et_xmlfile in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from openpyxl) (1.1.0) Requirement already satisfied: plotly in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (5.14.1) Requirement already satisfied: packaging in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from plotly) (23.0) Requirement already satisfied: tenacity>=6.2.0 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from plotly) (8.0.1) Requirement already satisfied: missingno in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (0.5.1) Requirement already satisfied: numpy in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from missingno) (1.22.4) Requirement already satisfied: scipy in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from missingno) (1.7.3) Requirement already satisfied: seaborn in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from missingno) (0.12.2) Requirement already satisfied: matplotlib in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from missingno) (3.6.3) Requirement already satisfied: cycler>=0.10 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (0.11.0) Requirement already satisfied: packaging>=20.0 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (23.0) Requirement already satisfied: pillow>=6.2.0 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (9.4.0) Requirement already satisfied: fonttools>=4.22.0 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (4.25.0) Requirement already satisfied: python-dateutil>=2.7 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (2.8.2) Requirement already satisfied: kiwisolver>=1.0.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (1.4.4) Requirement already satisfied: pyparsing>=2.2.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (3.0.9) Requirement already satisfied: contourpy>=1.0.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from matplotlib->missingno) (1.0.5) Requirement already satisfied: pandas>=0.25 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from seaborn->missingno) (2.0.1) Requirement already satisfied: pytz>=2020.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from pandas>=0.25->seaborn->missingno) (2022.7) Requirement already satisfied: tzdata>=2022.1 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from pandas>=0.25->seaborn->missingno) (2023.3) Requirement already satisfied: six>=1.5 in /Users/stino/opt/anaconda3/lib/python3.8/site-packages (from python-dateutil>=2.7->matplotlib->missingno) (1.16.0)
# Si usted está utilizando Colabolatory le puede ser útil este código para cargar los archivos.
try:
from google.colab import drive
drive.mount("/content/drive")
path = 'Dirección donde tiene los archivos en el Drive'
except:
print('Ignorando conexión drive-colab')
Ignorando conexión drive-colab
Mr. Lepin Mora quien es el gerente de una cotizada tienda de retail en Europa, les solicita si pueden analizar los datos de algunas de sus tiendas.
Para esto, el área de ventas les entrega el archivo online_retail_II.pickle con el que se les pide que cargue y visualicen algunas de las filas que componen el Dataset.
Realice una primera visualización de los datos y señale los atributos que componen el dataset. Señale las columnas que conforman el dataset, el tipo de variable presente en cada columna y comente que representa cada una de estas.
Respuesta:
df_retail = pd.read_pickle("online_retail_II.pickle")
df_retail = df_retail.astype(
{
"Invoice": "category",
"StockCode": "category",
"Description": str,
"Customer ID": "category",
}
)
df_retail.head()
| Invoice | StockCode | Description | Quantity | InvoiceDate | Price | Customer ID | Country | |
|---|---|---|---|---|---|---|---|---|
| 0 | 489434 | 85048 | 15CM CHRISTMAS GLASS BALL 20 LIGHTS | 12 | 2009-12-01 07:45:00 | 6.95 | 13085.0 | United Kingdom |
| 1 | 489434 | 79323P | PINK CHERRY LIGHTS | 12 | 2009-12-01 07:45:00 | 6.75 | 13085.0 | United Kingdom |
| 2 | 489434 | 79323W | WHITE CHERRY LIGHTS | 12 | 2009-12-01 07:45:00 | 6.75 | 13085.0 | United Kingdom |
| 3 | 489434 | 22041 | RECORD FRAME 7" SINGLE SIZE | 48 | 2009-12-01 07:45:00 | 2.10 | 13085.0 | United Kingdom |
| 4 | 489434 | 21232 | STRAWBERRY CERAMIC TRINKET BOX | 24 | 2009-12-01 07:45:00 | 1.25 | 13085.0 | United Kingdom |
En base a la primera visualización del dataset, Don Mora le solicita que realicen un análisis exploratorio de los datos, para esto les deberán realizar un análisis univariado y multivariado. De la revisión, ustedes deben explicar potenciales anomalías visualizadas y señalar si existe la necesidad de realizar una limpieza de datos.
Explique a que nos referimos con análisis univariable, multivariable y de datos faltantes. ¿Qué beneficios nos otorga estudiar estos datos?. Sea conciso con su respuesta y no escriba mas de 5 líneas para su respuesta.
Respuesta a la Pregunta:
Respuesta Aquí
A continuación, se le presentan dos funciones para analizar los datos que componen un dataframe. La primera de estas es la función profile_serie() la cual recibe una serie y le entrega un análisis detallado de los datos que conforman dicha serie.
Ejecute la funcion profile_serie() sobre cada serie para realizar un análisis univariado de estas. A continuación, comente acerca de el comportamiento de cada variable según las estadísticas descriptivas y los gráficos generados.
from pandas.api.types import is_numeric_dtype
from pandas.core.dtypes.common import is_datetime_or_timedelta_dtype
def profile_serie(serie_in, n_samples=1000, random_state=42):
serie = serie_in.copy()
profile = pd.Series(dtype='object')
profile["Type"] = serie.dtype
profile = pd.concat([profile, serie.describe()])
# profile = pd.Series([])
if is_numeric_dtype(serie):
profile["Negative"] = (serie < 0).sum()
profile["Negative (%)"] = (
str(round((serie < 0).sum() / len(serie) * 100, 2)) + " %"
)
profile["Zeros"] = (serie == 0).sum()
profile["Zeros (%)"] = (
str(round((serie == 0).sum() / len(serie) * 100, 2)) + " %"
)
profile["Kurt"] = serie.kurt()
profile["Skew"] = serie.skew()
profile[" "] = " " # espacio
profile["Missing cells"] = serie.isnull().sum()
profile["Missing cells (%)"] = (
str(round(serie.isnull().sum() / len(serie) * 100, 2)) + " %"
)
profile["Duplicate rows"] = serie.duplicated(False).sum()
profile["Duplicate rows (%)"] = (
str(round(serie.duplicated(False).sum() / len(serie) * 100, 2)) + " %"
)
profile["Total size in memory"] = str(serie.memory_usage(index=True)) + " bytes"
# profile = pd.concat([profile, description])
profile = profile.rename(
index={
"count": "Number of observations",
"mean": "Mean",
"std": "Std",
"min": "Min",
"max": "Max",
"unique": "Unique",
"top": "Top",
"freq": "Freq",
}
)
no_outliers_fig = None
if is_numeric_dtype(serie):
sampled_serie = serie.sample(n_samples, random_state=random_state)
fig = px.histogram(
sampled_serie, marginal="box", title=f"{serie.name} - With Outliers"
)
no_outliers = sampled_serie.loc[(np.abs(stats.zscore(sampled_serie)) < 3)]
# zscore = https://es.wikipedia.org/wiki/Unidad_tipificada
no_outliers_fig = px.histogram(
no_outliers, marginal="box", title=f"{serie.name} - Without Outliers"
)
elif is_datetime_or_timedelta_dtype(serie):
sampled_serie = serie.sample(n_samples, random_state=random_state)
fig = px.histogram(sampled_serie, marginal="box", title=f"{serie.name}")
else:
count = (
serie.value_counts()[0:100]
.reset_index()
.rename(columns = {'count': 'Count'})
)
fig = px.bar(
x=count[serie.name].astype(str),
y=count["Count"],
title=f"100 Most common categories of {serie.name}",
)
display(Markdown(f'## {serie.name} Profile'))
display(profile)
fig.show()
if no_outliers_fig:
no_outliers_fig.show()
# return fig, profile
profile_serie(df_retail['Price'])
Type float64
Number of observations 525461.0
Mean 4.688834
Std 146.126914
Min -53594.36
25% 1.25
50% 2.1
75% 4.21
Max 25111.09
Negative 3
Negative (%) 0.0 %
Zeros 3687
Zeros (%) 0.7 %
Kurt 64868.344873
Skew -140.768446
Missing cells 0
Missing cells (%) 0.0 %
Duplicate rows 524485
Duplicate rows (%) 99.81 %
Total size in memory 4203816 bytes
dtype: object
Análisis de la primera serie...
profile_serie(...)
Análisis de la n-esima serie...
En segundo lugar encontrará la función profile_df() que recibe un dataframe como entrada y realiza un análisis bivariado de todas las variables numéricas que conforman el dataframe, un analisis de la correlación de Pearson entre las variables numericas del dataframe y la matriz de datos faltantes.
def profile_df(dataframe_in):
df = dataframe_in.copy()
list_type = []
for col in list(df.columns):
if is_numeric_dtype(df[col]) or \
pd.core.dtypes.common.is_datetime_or_timedelta_dtype(df[col]):
list_type.append(col)
display(Markdown('## Bivariant Analysis:'))
for i in range(len(list_type)):
for j in range(i+1, len(list_type)):
plt.scatter(df[list_type[i]], df[list_type[j]])
plt.xlabel(list_type[i])
plt.ylabel(list_type[j])
plt.title(f"{list_type[i]} v/s {list_type[j]}")
plt.show()
display(Markdown('## Correlation:'))
fig_corr = px.imshow(df[list_type].corr())
fig_corr.show()
display(Markdown('## Missing Matrix:'))
fig, ax = plt.subplots(figsize=[15, 10])
msno.matrix(df, ax=ax, sparkline=False)
Como pudo ver en las secciones anteriores, los datos presentan valores erroneos, es por esto que se le solicita que realice una función que permita limpiar el dataset. Realice esta función en base observaciones propias y considere como imposible tener cantidades negativas en las ventas.
Una vez realizada la función, realice nuevamente el análisis exploratorio y comente las principales diferencias.
Respuesta:
> Código Aquí
Sin considerar los comentarios realizados en la sección 1.2 , Don Mora les pide obtener el Top de 30 productos que generan más ganancias para la tienda de retail. Deben considerar todo el registro temporal presente en el dataset y entregar la información en un gráfico de barras de los ingresos/cantidades v/s el nombre de los productos (Utilice plotly). ¿Los artículos más vendidos son los mismos que generan más ganancias?, Comente los resultados obtenidos.
Resultados:
> Código Aquí
El dueño del retail en su afán por saber más sobre los datos de su firma les solicita que grafiquen las ventas respecto al tiempo. Con esto les aclara que durante el día tienen muchas variaciones en sus ventas, por lo que les recomienda que consideren el registro temporal como año-mes-día. ¿Es posible observar datos extraños?, Comente lo que observa del gráfico.
def plot_ventas(dataframe):
pass
Eso ha sido todo para el lab de hoy, recuerden que el laboratorio tiene un plazo de entrega de una semana. Cualquier duda del laboratorio, no duden en contactarnos por mail o U-cursos.
